home *** CD-ROM | disk | FTP | other *** search
/ Video Toaster 4.3 / Video Toaster v4.3.iso / 4.2 / arexx / modeler / prick.lwm < prev    next >
Text File  |  1998-04-16  |  4KB  |  197 lines

  1. /* CMD: Random Surface Points
  2.  *
  3.  * Generate a set of points randomly distributed across the surface of
  4.  * an object by pricking it with many tiny needles.
  5.  */
  6. syscode = "Random Surface Points"
  7. statfil = 'T:RandomPoints.state'
  8. version = 'Prick v1.0'
  9.  
  10.     /* Boilerplate.
  11.      */
  12.     mxx="LWModelerARexx.port"
  13.     signal on error
  14.     signal on syntax
  15.     mxx_add = addlib(mxx,0)
  16.     if (~mxx_add) then exit
  17.     call addlib("rexxmathlib.library",0,-30,0)
  18.     call main
  19.     if (mxx_add) then call remlib(mxx)
  20.     exit
  21.  
  22.     syntax:
  23.     error:
  24.     t=Notify(1,'!Rexx Script Error','@'ErrorText(rc),'Line 'SIGL)
  25.     if (mxx_add) then call remlib(mxx)
  26.     exit
  27.  
  28.  
  29.  
  30. MAIN:
  31.  
  32. fg = curlayer()
  33. emp = emptylayers()
  34. if (words(emp) = 0) then do
  35.     call notify(1,"!Need a background layer for scratch work.")
  36.     return
  37. end
  38. temp = word(emp,1)
  39.  
  40. if (setup() = 0) then return
  41.  
  42.  
  43. /* Get bounding box for fg data.
  44.  */
  45. parse value boundingbox() with n x1 x2 y1 y2 z1 z2 .
  46. if (n = 0) then return
  47. lo = x1 y1 z1
  48. hi = x2 y2 z2
  49. dx = x2 - x1
  50. dy = y2 - y1
  51. dz = z2 - z1
  52.  
  53. /* Compute our slightly expanded box for the ends of the needles.
  54.  */
  55. exb = max(dx, dy, dz) / 20
  56. xx1 = x1 - exb
  57. xx2 = x2 + exb
  58. yy1 = y1 - exb
  59. yy2 = y2 + exb
  60. zz1 = z1 - exb
  61. zz2 = z2 + exb
  62.  
  63. /* Compute distribution cell size.  We want about "num" points
  64.  * distributed along the surface of the bounding box, so take that
  65.  * surface area, divide by num.  Square root of that is the cell
  66.  * edge size (s).  Also compute min allowed distance (md) and 
  67.  * tiny delta for needle construction (d).
  68.  */
  69. sa = 2 * (dx * dy + dy * dz + dz * dx)
  70. s = sqrt(sa / num)
  71. md = s / 4
  72. d = md / 20
  73. say "Cell edge size:" s "  Merge dist:" md
  74.  
  75. /* Goto background layer and build our lattice of needles.
  76.  */
  77. call setlayer(temp)
  78. call add_begin()
  79.  
  80. nx = dx % s
  81. ny = dy % s
  82. nz = dz % s
  83. say "Needle grid" nx ny nz
  84. call meter_begin(nx * ny + nx * nz + ny * nz, syscode)
  85.  
  86. do xi=1 to nx
  87.     x0 = x1 + (x2 - x1) / nx * (xi - 0.5)
  88.     do yi=1 to ny
  89.     y0 = y1 + (y2 - y1) / ny * (yi - 0.5)
  90.     xa = x0 + (randu()-0.5) * s
  91.     xb = x0 + (randu()-0.5) * s
  92.     ya = y0 + (randu()-0.5) * s
  93.     yb = y0 + (randu()-0.5) * s
  94.     i1 = add_point(xa ya   zz1)
  95.     i2 = add_point(xa ya+d zz1)
  96.     i3 = add_point(xb yb   zz2)
  97.     call add_polygon(i1 i2 i3)
  98.     call meter_step()
  99.     end yi
  100. end xi
  101.  
  102. do xi=1 to nx
  103.     x0 = x1 + (x2 - x1) / nx * (xi - 0.5)
  104.     do zi=1 to nz
  105.     z0 = z1 + (z2 - z1) / nz * (zi - 0.5)
  106.     xa = x0 + (randu()-0.5) * s
  107.     xb = x0 + (randu()-0.5) * s
  108.     za = z0 + (randu()-0.5) * s
  109.     zb = z0 + (randu()-0.5) * s
  110.     i1 = add_point(xa yy1 za)
  111.     i2 = add_point(xa yy1 za+d)
  112.     i3 = add_point(xb yy2 zb)
  113.     call add_polygon(i1 i2 i3)
  114.     call meter_step()
  115.     end zi
  116. end xi
  117.  
  118. do yi=1 to ny
  119.     y0 = y1 + (y2 - y1) / ny * (yi - 0.5)
  120.     do zi=1 to nz
  121.     z0 = z1 + (z2 - z1) / nz * (zi - 0.5)
  122.     ya = y0 + (randu()-0.5) * s
  123.     yb = y0 + (randu()-0.5) * s
  124.     za = z0 + (randu()-0.5) * s
  125.     zb = z0 + (randu()-0.5) * s
  126.     i1 = add_point(xx1 ya za)
  127.     i2 = add_point(xx1 ya za+d)
  128.     i3 = add_point(xx2 yb zb)
  129.     call add_polygon(i1 i2 i3)
  130.     call meter_step()
  131.     end zi
  132. end yi
  133.  
  134. call meter_end()
  135. call add_end()
  136.  
  137.  
  138. /* Perform the slice and leave only the points.
  139.  */
  140. call setblayer(fg)
  141. call soliddrill(SLICE)
  142. call removepols()
  143.  
  144. /* Delete the points that lie outside the bounding box of the
  145.  * original object, leaving the ones that intersected the interior
  146.  * surfaces.  Then merge points using our min distance.
  147.  */
  148. call sel_mode(USER)
  149. call sel_point(SET)
  150. d = exb / 2
  151. call sel_point(CLEAR, VOL, x1-d y1-d z1-d, x2+d y2+d z2+d)
  152. call cut()
  153. call mergepoints(md)
  154.  
  155. return
  156.  
  157.  
  158.  
  159. SETUP:
  160.  
  161. /* Setup state variables, reading stored ones, if any.
  162.  */
  163. num = 500
  164. if (exists(statfil)) then do
  165.     if (~open(state, statfil, 'R')) then break
  166.     if (readln(state) ~= version) then break
  167.     parse value readln(state) with num .
  168.     call close state
  169. end
  170.  
  171. /* Query user for their function and area to evaluate.
  172.  */
  173. call req_begin syscode
  174.  
  175. id_num = req_addcontrol("Approx Number of Points", 'n')
  176.  
  177. call req_setval id_divs, num, 500
  178.  
  179. if (~req_post()) then do
  180.     call req_end
  181.     return 0
  182. end
  183.  
  184. num = req_getval(id_num) % 1
  185.  
  186. call req_end
  187.  
  188. /* Save state now, in case something fails.
  189.  */
  190. if (open(state, statfil, 'W')) then do
  191.     call writeln state, version
  192.     call writeln state, num
  193.     call close state
  194. end
  195.  
  196. return 1
  197.